package moltencore.game.bubble;

import spark.math.Random;

public class BubbleRandomizer {
	private static final int INTERVAL_INDEX_ORDINARY = 1;
	private static final int INTERVAL_INDEX_GHOST = 2;
	private static final int INTERVAL_INDEX_RAINBOW = 3;
	private static final int INTERVAL_INDEX_BLAZING = 4;
	private static final int PROBABILITY_INTERVALS_SIZE = 5;
	private int differentOrdinaryBubblesCount;
	private float[] probabilityIntervals;

	public BubbleRandomizer(
			int differentOrdinaryBubblesCount, float ordinaryBubbleProbability,
			float rainbowBubbleProbability, float ghostBubbleProbability, float blazingBubbleProbability) {
		this.differentOrdinaryBubblesCount = differentOrdinaryBubblesCount;

		float sum = ordinaryBubbleProbability + rainbowBubbleProbability + ghostBubbleProbability + blazingBubbleProbability;

		probabilityIntervals = new float[PROBABILITY_INTERVALS_SIZE];
		probabilityIntervals[0] = 0.0f;
		probabilityIntervals[INTERVAL_INDEX_ORDINARY] = probabilityIntervals[INTERVAL_INDEX_ORDINARY - 1] + ordinaryBubbleProbability / sum;
		probabilityIntervals[INTERVAL_INDEX_GHOST] = probabilityIntervals[INTERVAL_INDEX_GHOST - 1] + ghostBubbleProbability / sum;
		probabilityIntervals[INTERVAL_INDEX_RAINBOW] = probabilityIntervals[INTERVAL_INDEX_RAINBOW - 1] + rainbowBubbleProbability / sum;
		probabilityIntervals[INTERVAL_INDEX_BLAZING] = probabilityIntervals[INTERVAL_INDEX_BLAZING - 1] + blazingBubbleProbability / sum;
	}

	public BubbleRandomizer(BubbleRandomizer other) {
		differentOrdinaryBubblesCount = other.differentOrdinaryBubblesCount;
		probabilityIntervals = new float[other.probabilityIntervals.length];
		for(int i = 0; i < other.probabilityIntervals.length; i++) {
			float probabilityInterval = other.probabilityIntervals[i];
			probabilityIntervals[i] = probabilityInterval;
		}
	}

	public Type randomBubbleType() {
		float random = Random.getInstance().nextFloat();
		if(valueInInterval(INTERVAL_INDEX_ORDINARY, random)) {
			return Type.randomOrdinary(differentOrdinaryBubblesCount);
		}
		else if(valueInInterval(INTERVAL_INDEX_GHOST, random)) {
			return Type.Ghost;
		}
		else if(valueInInterval(INTERVAL_INDEX_RAINBOW, random)) {
			return Type.Rainbow;
		}
		else if(valueInInterval(INTERVAL_INDEX_BLAZING, random)) {
			return Type.Blazing;
		}
		//this should be assert false but if for whatever reason (rounding errors or something that escapes my
		//knowledge about the way i implemented this class) the program does not end up in one of these ifs just
		//run the routine again - but again, this should never actually happen
		return randomBubbleType();
	}

	private boolean valueInInterval(int interval, float value) {
		return value >= probabilityIntervals[interval - 1] &&
		       value < probabilityIntervals[interval];
	}
}
